﻿using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Text.RegularExpressions;
using System.Diagnostics.Eventing.Reader;
using System.Xml.Linq;
using MySqlX.XDevAPI.Common;
using System.Diagnostics;
using RiskAlert_Entity;
using RiskAlert_Repository;

namespace RiskAlert_Service
{
    public abstract class BaseService<T>
    {
        protected MySqlConnection _connection;
        protected MySqlTransaction _transaction;
        protected ItemRepository _itemRepo;
        protected EvidenceRepository _evidRepo;
        protected readonly string EVIDENCE_DATABASE_PATH = @"C:\Users\LiHao\AAA_Using\Evidence_DataBase";
        public BaseService(MySqlConnection connection, MySqlTransaction transaction)
        {
            _connection = connection;
            _transaction = transaction;
        }
        public abstract void Create(T obj);
        public abstract void Delete(string PrimaryKey);
        public abstract T Read(string PrimaryKey);
        public abstract void Update(T obj, bool isConcat = false);
    }
    public class ItemService : BaseService<Item>
    {
        public ItemService(MySqlConnection connection, MySqlTransaction transaction, ItemRepository itemRepo) : base(connection, transaction)
        {
            _itemRepo = itemRepo;
        }
        public override void Create(Item item)
        {
            _itemRepo.Create(item);
        }
        public override void Delete(string ItemId)
        {
            _itemRepo.Delete(ItemId);
        }
        public override Item Read(string ItemId)
        {
            Item item = _itemRepo.Read(ItemId);
            return item;
        }
        public override void Update(Item item, bool isConcat = false)
        {
            _itemRepo.Update(item, isConcat);
        }
        public string GenerateItemId()
        {
            return DateTime.Now.ToString("yyyyMMddHHmmssfff");
        }

    }
    public class EvidenceService : BaseService<Evidence>
    {
        private readonly string url_regex = @"^(https?|ftp):\/\/(?:www\.)?([a-zA-Z0-9\-]+(\.[a-zA-Z]{2,}){1,})(:\d{1,5})?(\/[^\s?#]*)?(\?[^#\s]*)?(#[^\s]*)?$";
        private readonly string path_regex = @"^(?:(?:[a-zA-Z]:|\\\\[^\\/:*?""<>|]+\\[^\\/:*?""<>|]+|/)(?:\\|/)?|\.{1,2}(?:\\|/)?)(?:[^\\/:*?""<>|\r\n]+(?:\\|/)?)*$";
        public EvidenceService(MySqlConnection connection, MySqlTransaction transaction, EvidenceRepository evidRepo) : base(connection, transaction)
        {
            _evidRepo = evidRepo;
        }
        public override void Create(Evidence evidence)
        {
            _evidRepo.Create(evidence);
        }
        public override void Delete(string EvidenceId)
        {
            _evidRepo.Delete(EvidenceId);
        }
        public void DeleteAll(string ItemId)
        {
            _evidRepo.DeleteAll(ItemId);
        }
        public override Evidence Read(string PrimaryKey)
        {
            throw new NotImplementedException();
        }
        public List<Evidence> ReadLots(string ItemId)
        {
            List<Evidence> evidences;
            evidences = _evidRepo.ReadLots(ItemId);
            if (evidences != null)
            {
                return evidences;
            }
            else return null;

        }
        public override void Update(Evidence evidence, bool isConcat = false)
        {
            evidence.EvidenceStatu = getStatu(evidence.EvidenceStatu);
            _evidRepo.Update(evidence, isConcat);
        }
        public string getType(string evidence_str)
        {
            if (Regex.IsMatch(evidence_str, url_regex))
            {
                return "website";
            }
            else if (Regex.IsMatch(evidence_str, path_regex))
            {
                string file_extension = Path.GetExtension(evidence_str).ToLower();
                switch (file_extension)
                {
                    case ".mp4":
                    case ".avi":
                    case ".mkv": return "video";
                    case ".png":
                    case ".jpg":
                    case ".jpeg":
                    case ".webp":
                    case ".gif": return "image";
                    case ".mp3":
                    case ".acc":
                    case ".wav": return "audio";
                    case ".txt":
                    case ".doc":
                    case ".docx":
                    case ".xlsx": return "text";
                    default: throw new Exception("非法的文件类型！");
                }
            }
            else throw new Exception("非法的输入（evidence_str）！");
        }
        public string getStatu(string EvidenceStatu)
        {
            switch (EvidenceStatu)
            {
                case "1": return "verified";
                case "2": return "pending";
                case "3": return "invalid";
                case "4": return "partial";
                case "5": return "controversial";
                case "6": return "other";
                default: throw new Exception("非法的输入（EvidenceStatu）");
            }
        }
        public string getPath(Evidence evidence, string ItemName)
        {
            if (evidence.EvidenceType == "website")
            {
                return $@"{EVIDENCE_DATABASE_PATH}\website.txt";
            }
            else if (evidence.EvidenceType == "video" || evidence.EvidenceType == "image" || evidence.EvidenceType == "audio" || evidence.EvidenceType == "text")
            {
                return $@"{EVIDENCE_DATABASE_PATH}\{evidence.EvidenceType}\{evidence.EvidenceId}_{ItemName}_{evidence.RiskType}{Path.GetExtension(evidence.evidence_str)}";
            }
            else throw new Exception();
        }
        public string formatCount(int count)
        {
            string result = count.ToString();
            while (result.Length < 5)
            {
                result = result.Insert(0, "0");
            }
            //else { throw new Exception(">EvidenceCount< 达到上限！"); }
            return result;
        }
        public void writeFile(Evidence evidence, string ItemName)
        {
            using (StreamWriter writer = new StreamWriter(evidence.EvidencePath, true))
            {
                writer.WriteLine($"{evidence.EvidenceId}_{ItemName}_{evidence.RiskType}_{evidence.evidence_str}");
            }
        }
    }
    ///*
    public class InfoService
    {
        protected MySqlConnection _connection;
        protected MySqlTransaction _transaction;
        public static ItemService _itemService;
        public static EvidenceService _evidService;
        public static ItemRepository _itemRepo;
        public static EvidenceRepository _evidRepo;
        public InfoService(MySqlConnection connection)
        {
            _connection = connection;
            //MySqlCommand cmd = new MySqlCommand("set autocommit = 0;", _connection, _transaction);
            //cmd.ExecuteNonQuery();
            _itemRepo = new ItemRepository(_connection, _transaction);
            _evidRepo = new EvidenceRepository(_connection, _transaction);
            _itemService = new ItemService(_connection, _transaction, _itemRepo);
            _evidService = new EvidenceService(_connection, _transaction, _evidRepo);
        }
        public void OperateItemWithEvidence(Item item, Evidence evidence, bool isExist)
        {
            using (_transaction = _connection.BeginTransaction())
            {
                try
                {
                    if (isExist)
                    {
                        item.RiskType = evidence.RiskType;
                        _itemService.Update(item, true);
                        item.ItemId = _itemRepo.ReadIdByName(item.ItemName);
                    }
                    else
                    {
                        item.ItemId = _itemService.GenerateItemId();
                        _itemService.Create(item);
                    }
                    evidence.EvidenceId = GetEvidenceId(item.ItemId, _evidRepo.ReadMax(item.ItemId) + 1);
                    evidence.EvidenceStatu = _evidService.getStatu(evidence.EvidenceStatu);
                    evidence.EvidenceType = _evidService.getType(evidence.evidence_str);
                    evidence.EvidencePath = _evidService.getPath(evidence, item.ItemName);
                    if (Evidence.allowEvidenceType.Contains(evidence.EvidenceType))
                    {
                        if (evidence.EvidenceType == "website")
                        {
                            _evidService.writeFile(evidence, item.ItemName);
                        }
                        else
                        {
                            File.Copy(evidence.evidence_str, evidence.EvidencePath);
                        }
                    }
                    _evidService.Create(evidence);
                    _transaction.Commit();
                }
                catch (Exception ex)
                {
                    //文件读写的回滚逻辑手动实现
                    _transaction.Rollback();
                    Console.WriteLine(ex);
                    throw ex;
                }
            }
        }
        public void DeleteEvidence(string ItemName, int count)
        {
            using (_transaction = _connection.BeginTransaction())
            {
                string ItemId = _itemRepo.ReadIdByName(ItemName);
                string EvidenceId = GetEvidenceId(ItemId, count);
                _evidService.Delete(EvidenceId);
                _transaction.Commit();
            }
        }
        public void DeleteAll(string ItemName)
        {
            using (_transaction = _connection.BeginTransaction())
            {
                string ItemId = _itemRepo.ReadIdByName(ItemName);
                _itemService.Delete(ItemId);
                _evidService.DeleteAll(ItemId);
                _transaction.Commit();
            }
        }
        public Item ReadItem(string ItemName)
        {
            Item item = null;
            string ItemId = _itemRepo.ReadIdByName(ItemName);
            using (_transaction = _connection.BeginTransaction())
            {
                try
                {
                    item = _itemService.Read(ItemId);
                    _transaction.Commit();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                    _transaction.Rollback();
                }
            }
            return item;
        }
        public List<Evidence> ReadEvidences(string ItemName)
        {
            List<Evidence> evidences;
            using (_transaction = _connection.BeginTransaction())
            {
                string ItemId = _itemRepo.ReadIdByName(ItemName);
                evidences = _evidService.ReadLots(ItemId);
                _transaction.Commit();
            }
            if (evidences != null)
            {
                return evidences;
            }
            else return null;

        }
        public void UpdateItem(Item item, bool isConcat = false)
        {
            using (_transaction = _connection.BeginTransaction())
            {
                //item.ItemId = _itemRepo.ReadIdByName(item.ItemName);
                _itemService.Update(item, isConcat);
                _transaction.Commit();
            }
        }
        public void UpdateEvidence(Evidence evidence, bool isConcat = false)
        {
            using (_transaction = _connection.BeginTransaction())
            {
                _evidService.Update(evidence, isConcat);
                _transaction.Commit();
            }
        }







        private string GetEvidenceId(string ItemId, int count)
        {
            return $"{ItemId}_{_evidService.formatCount(count)}";
        }
    }


    //*/
}
